package com.childenglish.config;

import com.childenglish.shiro.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(1_800_000); // 30 min
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionValidationInterval(3_600_000); // 1 h
        // 允许多会话：不限制同一用户的并发会话数
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        shiroFilter.setLoginUrl("/login");
        shiroFilter.setUnauthorizedUrl("/unauthorized");

        // 注册 CORS 过滤器
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("cors", corsFilter());
        shiroFilter.setFilters(filters);

        Map<String, String> filterMap = new LinkedHashMap<>();
        /* ===== 匿名放行 ===== */
        filterMap.put("/", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/logout", "anon"); // 登出接口，允许匿名访问
        filterMap.put("/user/info", "anon");
        filterMap.put("/user/permissions", "anon");
        filterMap.put("/unauthorized", "anon");
        filterMap.put("/error", "anon");
        filterMap.put("/admin/**", "anon");
        filterMap.put("/health", "anon");
        filterMap.put("/test", "anon");
        filterMap.put("/cluster/**", "anon");
        filterMap.put("/api/check-username", "anon"); // 用户名检查
        filterMap.put("/api/register", "anon");
        filterMap.put("/api/register-child", "anon"); // 儿童注册
        filterMap.put("/api/validate-password", "anon"); // 密码验证
        filterMap.put("/api/validate-email", "anon"); // 邮箱验证
        filterMap.put("/api/validate-phone", "anon"); // 手机号验证
        filterMap.put("/api/classes", "anon");
        filterMap.put("/api/classes/**", "anon"); // 班级相关接口（包括创建、更新、删除）
        filterMap.put("/api/students", "anon"); // 学生列表接口
        filterMap.put("/api/students/**", "anon"); // 学生相关接口（包括详情接口）
        filterMap.put("/api/students/debug", "anon"); // 学生调试接口
        filterMap.put("/api/captcha", "anon"); // 验证码获取端点
        filterMap.put("/api/csrf-token", "anon"); // CSRF Token获取端点
        filterMap.put("/csrf-token", "anon"); // CSRF Token获取端点（备选）
        filterMap.put("/api/encryption/**", "anon"); // 数据加密演示端点
        filterMap.put("/api/forgot-password/**", "anon"); // 找回密码端点
        filterMap.put("/file/**", "cors,anon"); // 文件上传下载API，允许匿名访问，需要CORS支持
        filterMap.put("/api/guidance/**", "anon"); // 指导相关接口（暂时允许匿名，实际项目中应改为authc）
        filterMap.put("/learning/leaderboard", "cors,anon"); // 排行榜接口，允许匿名访问（需要CORS支持）
        filterMap.put("/learning/game/levels", "cors,anon"); // 游戏关卡接口，允许匿名访问（需要CORS支持）

        /* ===== 静态资源 ===== */
        filterMap.put("/static/**", "anon");
        filterMap.put("/css/**", "anon");
        filterMap.put("/js/**", "anon");
        filterMap.put("/images/**", "anon");
        filterMap.put("/favicon.ico", "anon");

        /* ===== 需要认证 ===== */
        filterMap.put("/learning/**", "cors,authc"); // 添加cors过滤器，确保CORS预检请求能通过
        filterMap.put("/parent/**", "cors,authc");
        filterMap.put("/teaching/**", "cors,authc");
        filterMap.put("/system/**", "cors,authc");

        /* ===== 其余全部先过 CORS 再认证 ===== */
        filterMap.put("/**", "cors,authc");

        shiroFilter.setFilterChainDefinitionMap(filterMap);
        return shiroFilter;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();

        /* ===== 允许的前端 dev 地址 ===== */
        config.addAllowedOrigin("http://localhost:5173"); // Vite 默认
        config.addAllowedOrigin("http://localhost:5174"); // Vite 其他端口
        config.addAllowedOrigin("http://localhost:5175"); // Vite 其他端口
        config.addAllowedOrigin("http://localhost:3000"); // React 常用
        config.addAllowedOrigin("http://localhost:8080"); // 自身
        config.addAllowedOrigin("http://localhost:8081"); // 集群节点
        config.addAllowedOrigin("http://localhost:8082");
        config.addAllowedOrigin("http://localhost:80");
        config.addAllowedOrigin("http://localhost");
        config.addAllowedOrigin("http://localhost:8000"); // Python HTTP服务器（测试页面）
        config.addAllowedOrigin("http://127.0.0.1:8000"); // Python HTTP服务器
        config.addAllowedOrigin("http://127.0.0.1:5173");
        config.addAllowedOrigin("http://127.0.0.1:5174"); // Vite 其他端口
        config.addAllowedOrigin("http://127.0.0.1:5175"); // Vite 其他端口
        config.addAllowedOrigin("http://127.0.0.1:8080");
        
        // 允许暴露自定义响应头（重要：用于CSRF Token）
        config.addExposedHeader("X-CSRF-TOKEN");

        /* ===== 允许任何头、方法、凭证 ===== */
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setAllowCredentials(true);

        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}